<template>
  <div ref="container" class="model-container"></div>
</template>

<script setup>
import { ref, watch, onMounted, onBeforeUnmount } from 'vue';
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { OBJLoader } from 'three/addons/loaders/OBJLoader.js';
import { FBXLoader } from 'three/addons/loaders/FBXLoader.js';
import { STLLoader } from 'three/addons/loaders/STLLoader.js';
import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';

const props = defineProps({
  modelData: {
    type: [String, ArrayBuffer],
    required: true
  },
  modelType: {
    type: String,
    required: true,
    validator: (value) => ['gltf', 'glb', 'obj', 'fbx', 'stl'].includes(value)
  },
  backgroundColor: {
    type: String,
    default: '#f0f0f0'
  },
  showAxes: {
    type: Boolean,
    default: true
  }
});

const emit = defineEmits(['loading', 'loaded', 'error']);

const container = ref(null);
let scene, camera, renderer, controls, currentModel;

// 初始化场景
function initScene() {
  // 创建场景
  scene = new THREE.Scene();
  scene.background = new THREE.Color(props.backgroundColor);
  
  // 创建相机
  camera = new THREE.PerspectiveCamera(
    75,
    container.value.clientWidth / container.value.clientHeight,
    0.1,
    1000
  );
  camera.position.set(5, 5, 5);
  
  // 创建渲染器
  renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setSize(container.value.clientWidth, container.value.clientHeight);
  container.value.appendChild(renderer.domElement);
  
  // 添加轨道控制器
  controls = new OrbitControls(camera, renderer.domElement);
  controls.enableDamping = true;
  controls.dampingFactor = 0.05;
  
  // 添加光源
  const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
  scene.add(ambientLight);
  
  const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
  directionalLight.position.set(5, 10, 7);
  scene.add(directionalLight);

  // 添加坐标轴辅助
  if (props.showAxes) {
    const axesHelper = new THREE.AxesHelper(5);
    scene.add(axesHelper);
  }
}

// 加载模型
async function loadModel() {
  if (!props.modelData) return;
  
  emit('loading', true);
  
  try {
    // 清除旧模型
    if (currentModel) {
      scene.remove(currentModel);
      currentModel = null;
    }
    
    switch (props.modelType) {
      case 'gltf':
      case 'glb':
        await loadGLTF(props.modelData);
        break;
      case 'obj':
        await loadOBJ(props.modelData);
        break;
      case 'fbx':
        await loadFBX(props.modelData);
        break;
      case 'stl':
        await loadSTL(props.modelData);
        break;
      default:
        throw new Error('Unsupported model format');
    }
    
    emit('loaded');
  } catch (error) {
    console.error('Error loading model:', error);
    emit('error', error);
  } finally {
    emit('loading', false);
  }
}

// 加载GLTF/GLB模型
async function loadGLTF(data) {
  const loader = new GLTFLoader();
  
  // 设置DRACO解码器
  const dracoLoader = new DRACOLoader();
  dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.5.6/');
  loader.setDRACOLoader(dracoLoader);
  
  let gltf;
  if (typeof data === 'string') {
    // GLTF文本格式
    gltf = await loader.parseAsync(data, '', (res) => {
      const progress = (res.loaded / res.total * 100).toFixed(2);
      emit('progress', parseFloat(progress));
    });
  } else {
    // GLB二进制格式
    gltf = await loader.parseAsync(data, '', (res) => {
      const progress = (res.loaded / res.total * 100).toFixed(2);
      emit('progress', parseFloat(progress));
    });
  }
  
  currentModel = gltf.scene;
  scene.add(currentModel);
  centerModel(currentModel);
}

// 加载OBJ模型
async function loadOBJ(data) {
  const loader = new OBJLoader();
  currentModel = loader.parse(data);
  scene.add(currentModel);
  centerModel(currentModel);
}

// 加载FBX模型
async function loadFBX(data) {
  const loader = new FBXLoader();
  currentModel = loader.parse(data);
  scene.add(currentModel);
  centerModel(currentModel);
}

// 加载STL模型
async function loadSTL(data) {
  const loader = new STLLoader();
  const geometry = loader.parse(data);
  
  const material = new THREE.MeshStandardMaterial({
    color: 0xaaaaaa,
    metalness: 0.5,
    roughness: 0.5,
  });
  
  currentModel = new THREE.Mesh(geometry, material);
  scene.add(currentModel);
  centerModel(currentModel);
}

// 居中并缩放模型
function centerModel(model) {
  const box = new THREE.Box3().setFromObject(model);
  const center = box.getCenter(new THREE.Vector3());
  const size = box.getSize(new THREE.Vector3());
  
  // 居中
  model.position.x += (model.position.x - center.x);
  model.position.y += (model.position.y - center.y);
  model.position.z += (model.position.z - center.z);
  
  // 缩放以适应视图
  const maxDim = Math.max(size.x, size.y, size.z);
  const scale = 5 / maxDim;
  model.scale.set(scale, scale, scale);
  
  // 更新相机位置
  camera.position.set(0, 0, 10);
  controls.update();
}

// 处理窗口大小变化
function onWindowResize() {
  camera.aspect = container.value.clientWidth / container.value.clientHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(container.value.clientWidth, container.value.clientHeight);
}

// 动画循环
function animate() {
  requestAnimationFrame(animate);
  controls.update();
  renderer.render(scene, camera);
}

// 监听props变化
watch(() => [props.modelData, props.modelType], () => {
  loadModel();
});

onMounted(() => {
  initScene();
  animate();
  window.addEventListener('resize', onWindowResize);
  loadModel();
});

onBeforeUnmount(() => {
  window.removeEventListener('resize', onWindowResize);
  if (renderer) {
    renderer.dispose();
  }
});
</script>

<style scoped>
.model-container {
  width: 100%;
  height: 100%;
  min-height: 500px;
}
</style>